package com.wstuo.common.jbpm;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.wstuo.common.security.utils.AppConfigUtils;
import com.wstuo.common.jbpm.dto.NodeDTO;


/**
 * 流程自定义
 * @author wstuo
 *
 */
public class FlowDesigner {
	public static final String PROCESS_FILE_PATH=AppConfigUtils.getInstance().getProcessFilePath();
	private static final Logger LOGGER = Logger.getLogger(FlowDesigner.class ); 
	/**
	 * 原始XML文件转JPDL
	 * @param rawXml
	 */
	public void RawToJPDL(String rawXml){
		//把传来过的内容写入指定的XML文件
		File jpdlRawFile = new File(PROCESS_FILE_PATH+"/jpdlRaw.xml");
		try {
			FileUtils.writeStringToFile(jpdlRawFile, rawXml,"UTF-8");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			LOGGER.error("write rawXml string to jpdlRawFile error",e1);
		}
		//XSL模块文件
		File xsltFile = new File(PROCESS_FILE_PATH+"/jpdl.xsl");
		//转成功后保存的文件
		File jpdlFile = new File(PROCESS_FILE_PATH+"/result.jpdl.xml");
		
		Source xmlsource = new StreamSource(jpdlRawFile);
		Source xsltsource = new StreamSource(xsltFile);
		TransformerFactory transfact = TransformerFactory.newInstance();
		Transformer trans;
		StringWriter out = new StringWriter();
        Result output = new StreamResult( out ); 
		try {
			trans = transfact.newTransformer(xsltsource);
			try {
				trans.transform(xmlsource,output);
				out.flush();
				
				try {
					FileUtils.writeStringToFile(jpdlFile, out.toString(),"UTF-8");
				} catch (IOException e) {
					// TODO Auto-generated catch block
					LOGGER.error("write trans string to jpdlFile error",e);
				}
				
			} catch (TransformerException e) {
				LOGGER.error("RawToJPDL TransformerException",e);
			}
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			LOGGER.error("RawToJPDL TransformerConfigurationException",e);
		}
	}
	/**
	 * 获取指定元素
	 * @param xmlfile
	 * @param nodeTag
	 * @return List<NodeDTO>
	 */
	public List<NodeDTO> findNodeByNodeName(File xmlfile,String nodeTag){
		List<NodeDTO> list = new ArrayList<NodeDTO>();
		//定义DOM工厂
		DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		Document doc;
		try {
			//得到工厂对象
			builder = factory.newDocumentBuilder();
			try {
				//解析XML
				doc = builder.parse(xmlfile);
				//查找指定的指定
				NodeList taskNode = doc.getElementsByTagName(nodeTag);
				for(int i=0;i<taskNode.getLength();i++){
					NodeDTO nodeDTO = new NodeDTO();
					nodeDTO.setNodeTag(nodeTag);
					Map<String,String> attributesMap = new HashMap<String, String>();
					Node node =taskNode.item(i);
					nodeDTO.setIndex(i);
					nodeDTO.setNodeName(node.getAttributes().getNamedItem("name").getNodeValue());
					NamedNodeMap nodeMap=node.getAttributes();
					for(int j=0;j<nodeMap.getLength();j++){
						attributesMap.put(nodeMap.item(j).getNodeName(), nodeMap.item(j).getNodeValue());
					}
					nodeDTO.setNodeAttribute(attributesMap);
					
					list.add(nodeDTO);
				}
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner SAXException", e);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner IOException", e);
			}
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			LOGGER.error("FlowDesigner ParserConfigurationException", e);
		}
		
		return list;
	}
	/**
	 * 获取指定元素
	 * @param xmlfile
	 * @param nodeTag
	 * @return List<NodeDTO>
	 */
	public Map<String,Map<String,String>> findNodeMapByNodeName(File xmlfile,String nodeTag){
		Map<String,Map<String,String>> map = new HashMap<String, Map<String,String>>();
		//定义DOM工厂
		DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		Document doc;
		try {
			//得到工厂对象
			builder = factory.newDocumentBuilder();
			try {
				//解析XML
				doc = builder.parse(xmlfile);
				//查找指定的指定
				NodeList taskNode = doc.getElementsByTagName(nodeTag);
				
				for(int i=0;i<taskNode.getLength();i++){
					Map<String,String> attributesMap = new HashMap<String, String>();
					Node node =taskNode.item(i);
					NamedNodeMap nodeMap=node.getAttributes();
					for(int j=0;j<nodeMap.getLength();j++){
						attributesMap.put(nodeMap.item(j).getNodeName(), nodeMap.item(j).getNodeValue());
					}
					attributesMap.put("index", i+"");
					map.put(node.getAttributes().getNamedItem("name").getNodeValue(), attributesMap);
				}
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner SAXException", e);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner IOException", e);
			}
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			LOGGER.error("FlowDesigner ParserConfigurationException", e);
		}
		
		return map;
	}
	/**
	 * 更新元素
	 * @param xmlfile
	 * @param nodeDTO
	 */
	public void updateNode(String xmlfile, Map<Integer,Map<String,String>> map,String tag){
		DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		Document doc;
		try {
			builder = factory.newDocumentBuilder();
			try {
				doc = builder.parse(new File(xmlfile));
				//查找指定的元素
				NodeList element = doc.getElementsByTagName(tag);
				for(Integer key:map.keySet()){
					Node node =element.item(key);
					Element el=(Element)node;
					Map<String,String> attrs=map.get(key);
					for(String attr:attrs.keySet()){
						el.setAttribute(attr, attrs.get(attr));
					}
				}
				saveXml(doc,xmlfile);
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner SAXException", e);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner IOException", e);
			}
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			LOGGER.error("FlowDesigner ParserConfigurationException", e);
		}
	}
	public void updateNode(File xmlfile,NodeDTO nodeDTO){
		DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		Document doc;
		try {
			builder = factory.newDocumentBuilder();
			try {
				doc = builder.parse(xmlfile);
				//查找指定的元素
				NodeList element = doc.getElementsByTagName(nodeDTO.getNodeTag());
				Node node =element.item(nodeDTO.getIndex());
				Element el=(Element)node;
				for(String key:nodeDTO.getNodeAttribute().keySet()){
					el.setAttribute(key, nodeDTO.getNodeAttribute().get(key));
				}
				saveXml(doc,PROCESS_FILE_PATH+"/result.jpdl.xml");
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner SAXException", e);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner IOException", e);
			}
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			LOGGER.error("FlowDesigner ParserConfigurationException", e);
		}
	}
	/**
	 * 保存XML
	 * @param doc
	 * @param filename
	 */
	public void saveXml(Document doc,String filename){
		/** 将document中的内容写入文件中   */ 
        TransformerFactory tFactory = TransformerFactory.newInstance();    
        Transformer transformer;
		try {
			transformer = tFactory.newTransformer();
	        DOMSource source = new DOMSource(doc);  
	        StreamResult result = new StreamResult(new File(filename));    
	        try {
				transformer.transform(source, result);
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				LOGGER.error("FlowDesigner TransformerException", e);
			}  
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			LOGGER.error("FlowDesigner TransformerConfigurationException", e);
		}  
	}
	
}
